package com.xiaoshuidi.cloud.module.system.service.oauser;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.collection.CollectionUtils;
import com.xiaoshuidi.cloud.framework.datapermission.core.util.DataPermissionUtils;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.system.controller.admin.oauser.vo.OaUserSearchVO;
import com.xiaoshuidi.cloud.module.system.controller.admin.oauser.vo.UserImportExcelVO;
import com.xiaoshuidi.cloud.module.system.controller.admin.oauser.vo.UserImportRespVO;
import com.xiaoshuidi.cloud.module.system.convert.user.UserConvert;
import com.xiaoshuidi.cloud.module.system.dal.dataobject.oauser.OaUsersDO;
import com.xiaoshuidi.cloud.module.system.dal.dataobject.user.AdminUserDO;
import com.xiaoshuidi.cloud.module.system.dal.mysql.oauser.OaUserMapper;
import com.xiaoshuidi.cloud.module.system.dal.mysql.user.AdminUserMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;

import static com.xiaoshuidi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xiaoshuidi.cloud.module.system.enums.ErrorCodeConstants.*;
import static com.xiaoshuidi.cloud.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS;

/**
	* @author dujianguang
	*/
@Service
public class OaUserServiceImpl implements OaUserService{
		@Resource
		private OaUserMapper oaUserMapper;
		@Resource
		private AdminUserMapper userMapper;

		@Override
		@TenantIgnore
		public PageResult<OaUsersDO> getPage(OaUserSearchVO searchVO) {
				return oaUserMapper.selectPage(searchVO);
		}

		@Override
		@TenantIgnore
		@Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
		public UserImportRespVO importUserList(List<UserImportExcelVO> importUsers) {
				if (CollUtil.isEmpty(importUsers)) {
						throw exception(USER_IMPORT_LIST_IS_EMPTY);
				}

				UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
												.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
				importUsers.forEach(importUser -> {
						// 校验，判断是否有不符合的原因
						OaUsersDO existUser;
						try {
								existUser = validateUserForCreateOrUpdate(importUser.getUsername(), importUser.getMobile());
						} catch (ServiceException ex) {
								respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
								return;
						}

						if (existUser == null) {
								OaUsersDO oaUsersDO = new OaUsersDO();
								oaUsersDO.setUsername(importUser.getUsername());
								oaUsersDO.setMobile(importUser.getMobile());
								oaUserMapper.insert(oaUsersDO);
								respVO.getCreateUsernames().add(importUser.getUsername());
								return;
						}

				});
				return respVO;
		}

		private OaUsersDO validateUserForCreateOrUpdate(String username, String mobile) {
				Pair<String, OaUsersDO> existingUser = new MutablePair<>();
				// 关闭数据权限，避免因为没有数据权限，查询不到数据，进而导致唯一校验不正确
				DataPermissionUtils.executeIgnore(() -> {

						// 校验用户名唯一
						OaUsersDO user = validateUsernameUnique(username);
						existingUser.setValue(user);
						// 校验手机号唯一
						validateMobileUnique(mobile);
						// 检测手机号是否在租赁系统中存在
						validateSystemByMobile(mobile);
				});
				return existingUser.getValue();
		}

		private void validateSystemByMobile(String mobile) {
				if (StrUtil.isBlank(mobile)) {
						return;
				}
				AdminUserDO user = userMapper.selectOne(AdminUserDO::getMobile,mobile);
				if (ObjectUtils.isNotEmpty(user)) {
						return;
				}
				if (user == null) {
						throw  exception(USER_PHONE_EXISTS);
				}

		}

		private void validateMobileUnique(String mobile) {
				if (StrUtil.isBlank(mobile)) {
						return;
				}
				OaUsersDO user = oaUserMapper.selectOne(OaUsersDO::getMobile,mobile);
				if (user == null) {
						return;
				}
				if (ObjectUtils.isNotEmpty(user)) {
						throw exception(USER_MOBILE_EXISTS);
				}
		}

		private OaUsersDO validateUsernameUnique(String username) {
				if (StrUtil.isBlank(username)) {
						return null;
				}
				OaUsersDO user = oaUserMapper.selectOne(OaUsersDO::getUsername,username);
				if (user == null) {
						return null;
				}
				if (ObjectUtils.isNotEmpty(user)) {
						throw exception(USER_USERNAME_EXISTS);
				}
				return user;
		}
}
